package jp.co.menox.tmserver.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slim3.datastore.Datastore;
import org.slim3.datastore.ModelQuery;

import jp.co.menox.tmcommon.common.DataConst;
import jp.co.menox.tmcommon.meta.LendingHistoryMeta;
import jp.co.menox.tmcommon.model.Lending;
import jp.co.menox.tmcommon.model.LendingHistory;
import jp.co.menox.tmserver.channel.MessageSender;
import jp.co.menox.tmserver.dao.LendingDao;
import jp.co.menox.tmserver.dao.LendingHistoryDao;

/**
 * 貸し借り履歴関連サービス
 * @author
 *
 */
public class LendingHistoryService extends TmServerServiceBase<LendingHistory, LendingHistoryDao> {

    private LendingDao lendingDao;

    public LendingHistoryService() {
        dao = new LendingHistoryDao();
        lendingDao = new LendingDao();
    }

    
    // TODO: 仕様不明確のためとりあえずガワだけ
    // 承認、返却、など業務ロジックに対応するデータアクセスを記述すること。以下みたいなイメージ。
//    public LendingHistory updateForContract() {
//        return null;
//    }
//    public LendingHistory updateForCompletion() {
//        return null;
//    }


    // ****該当ユーザに関連する貸し借りリスト

    /**
     * 該当ユーザが貸与者であり、該当ステータスになっている貸したいものテーブルのリストを取得
     * @param userId
     * @param status
     * @return
     */
    public List<Lending> getLendingListByLendingUser(long userId, int status) {
        
        LendingHistoryMeta m = LendingHistoryMeta.get();
        ModelQuery<LendingHistory> query = Datastore.query(m);

        // 貸与者ID
        query = query.filter(m.lendingUser.equal(userId));
        
        return getLendingList(query, status);
    }
    
    /**
     * 該当ユーザが借用者であり、該当ステータスになっている貸したいものテーブルのリストを取得
     * @param userId
     * @param status
     * @return
     */
    public List<Lending> getLendingListByBorrowingUser(long userId, int status) {
        
        LendingHistoryMeta m = LendingHistoryMeta.get();
        ModelQuery<LendingHistory> query = Datastore.query(m);

        // 貸与者ID
        query = query.filter(m.borrowingUser.equal(userId));
        
        return getLendingList(query, status);
    }
    
    /**
     * 該当ユーザが借用者であり、申請却下ステータスになっている貸したいものテーブルのリストを取得<br />
     * 該当日以降を表示
     * @param userId
     * @param rejectedDate
     * @return
     */
    public List<Lending> getRejectedLendingListByBorrowingUser(long userId, Date rejectedDate) {
        
        LendingHistoryMeta m = LendingHistoryMeta.get();
        ModelQuery<LendingHistory> query = Datastore.query(m);

        // 貸与者ID
        query = query.filter(m.borrowingUser.equal(userId));

        // 申請却下日
        query = query.filter(m.rejectedDate.greaterThanOrEqual(rejectedDate));

        return getLendingList(query, DataConst.STATUS_SHINSEIKYAKKA);
    }
    
    /**
     * 指定したqueryに追加して、該当ステータスになっている貸したいものテーブルのリストを取得
     * @param query
     * @param status
     * @return
     */
    private List<Lending> getLendingList(ModelQuery<LendingHistory> query, int status) {
        
        LendingHistoryMeta m = LendingHistoryMeta.get();

        // ステータス
        query = query.filter(m.statusType.equal(status));
        // 有効なもの（論理削除されていない）
        query = query.filter(m.wasDeleted.equal(false));
        // 更新日順
        query = query.sortInMemory(m.created.desc);
        query = query.sortInMemory(m.modified.desc);
        
        // 対象ステータスのlendingHistory
        List<LendingHistory> historyModelList = query.asList();
        if (historyModelList == null) {
            return Collections.<Lending>emptyList();
        }

        // 対象
        List<Lending> modelList = new ArrayList<Lending>();
        for (LendingHistory history : historyModelList) {
            modelList.add(lendingDao.select(history.getLendingId()));
        }
        
        return modelList;
    }
    /**
     * 貸与者
     * 指定したqueryに追加して、該当ステータスになっている貸出履歴テーブルのリストを取得
     * @param userId
     * @return List<LendingHistory>
     */
    public List<LendingHistory> getLendingHistoryList(long userId) {
        
        List<LendingHistory> modelList = dao.getLendingList(userId);
        
        return modelList;
    }
    /**
     * 借用者
     * 指定したqueryに追加して、該当ステータスになっている貸出履歴テーブルのリストを取得
     * @param userId
     * @return List<LendingHistory>
     */
    public List<LendingHistory> getBorrowingHistoryList(long userId) {
        
        List<LendingHistory> modelList = dao.getBorrowingList(userId);
        
        return modelList;
    }
    /**
     * 貸出　品物名mapを取得する
     * @return
     */
    public Map<Long, String> getLendingNameMap() {
        return lendingDao.getLendingNameMap();
    }
    /**
     * 貸出　コメントmapを取得する
     * @return
     */
    public Map<Long, String> getLendingCommentMap() {
        return lendingDao.getLendingCommentMap();
    }
    /**
     * 貸出　カテゴリID mapを取得する
     * @return
     */
    public Map<Long, String> getLendingCategoryMap() {
        return lendingDao.getLendingCategoryMap();
    }

    /**
     * 該当の品物の最後のhistoryを取得
     * @param lendingId 貸したいものID
     * @return
     */
    public LendingHistory getCurrentHistory(long lendingId) {
        
        LendingHistoryMeta m = LendingHistoryMeta.get();
        ModelQuery<LendingHistory> query = Datastore.query(m);

        // 有効なもの（論理削除されていない）
        query = query.filter(m.wasDeleted.equal(false));

        // 品物（貸したいものID）
        query = query.filter(m.lendingId.equal(lendingId));

        // 作成日順
        query = query.sortInMemory(m.created.desc);
        
        // 対象のlendingHistory
        List<LendingHistory> historyModelList = query.asList();
        if (historyModelList == null || historyModelList.size() == 0) {
            return null;
        }

        return historyModelList.get(0);
    }
    
    /**
     * 予約可能であるかを取得する<br />
     * 引数の貸せるものリストを対象とし、LendingHistoryの状態より判定する
     * @param modelList
     * @return
     */
    public List<Boolean> getCanReserve(List<Lending> modelList) {
        if (modelList == null || modelList.size() == 0) {
            return Collections.<Boolean>emptyList();
        }
        
        List<Boolean> canReserveList = new ArrayList<Boolean>();
        for (Lending model : modelList) {
            // lendingに対応する最後のhistoryで確認する
            LendingHistory historyModel = getCurrentHistory(model.getId());
            if (historyModel == null) {
                canReserveList.add(true);
            } else if (historyModel.getStatusType() == DataConst.STATUS_HENKYAKUZUMI 
                    || historyModel.getStatusType() == DataConst.STATUS_SHINSEIKYAKKA) {
                canReserveList.add(true);
            } else {
                canReserveList.add(false);
            }
        }

        return canReserveList;
    }
    
    
    // ****
    
    @Override
    public LendingHistory insert(LendingHistory model) {
        // TODO Auto-generated method stub
        return super.insert(model);
    }
 
    @Override
    public LendingHistory update(LendingHistory model) {
        // TODO Auto-generated method stub
        return super.update(model);
    }

    @Override
    public LendingHistory delete(LendingHistory model) {
        // TODO Auto-generated method stub
        return super.delete(model);
    }

    
    // **** イベント処理用メソッド

    @Override
    public void onInserted(LendingHistory model) {
        // TODO: ステータスをチェックしてメール送信やら何やらを記述する想定

//        // 現在ログイン中のユーザのメニューに表示
//        MessageSender.sendCurrentModelList(model);
        
        super.onInserted(model);
    }

    @Override
    public void onUpdated(LendingHistory model) {
        // TODO: ステータスをチェックしてメール送信やら何やらを記述する想定

//        // 現在ログイン中のユーザのメニューに表示
//        MessageSender.sendCurrentModelList(model);

        super.onUpdated(model);
    }

    @Override
    public void onDeleted(LendingHistory model) {

//        // 現在ログイン中のユーザのメニューに表示
//        MessageSender.sendCurrentModelList(model);

        super.onDeleted(model);
    }

    
}
